Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (C) 2009-2010 Francisco Jerez.
  3.  * All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining
  6.  * a copy of this software and associated documentation files (the
  7.  * "Software"), to deal in the Software without restriction, including
  8.  * without limitation the rights to use, copy, modify, merge, publish,
  9.  * distribute, sublicense, and/or sell copies of the Software, and to
  10.  * permit persons to whom the Software is furnished to do so, subject to
  11.  * the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice (including the
  14.  * next paragraph) shall be included in all copies or substantial
  15.  * portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20.  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  21.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  *
  25.  */
  26.  
  27. #include "tnl/t_context.h"
  28. #include "tnl/t_pipeline.h"
  29. #include "tnl/t_vertex.h"
  30.  
  31. #define SWTNL_VBO_SIZE 65536
  32.  
  33. static enum tnl_attr_format
  34. swtnl_get_format(int type, int fields) {
  35.         switch (type) {
  36.         case GL_FLOAT:
  37.                 switch (fields){
  38.                 case 1:
  39.                         return EMIT_1F;
  40.                 case 2:
  41.                         return EMIT_2F;
  42.                 case 3:
  43.                         return EMIT_3F;
  44.                 case 4:
  45.                         return EMIT_4F;
  46.                 default:
  47.                         assert(0);
  48.                 }
  49.         case GL_UNSIGNED_BYTE:
  50.                 switch (fields) {
  51.                 case 4:
  52.                         return EMIT_4UB_4F_RGBA;
  53.                 default:
  54.                         assert(0);
  55.                 }
  56.         default:
  57.                 assert(0);
  58.         }
  59. }
  60.  
  61. static struct swtnl_attr_info {
  62.         int type;
  63.         int fields;
  64. } swtnl_attrs[VERT_ATTRIB_MAX] = {
  65.         [VERT_ATTRIB_POS] = {
  66.                 .type = GL_FLOAT,
  67.                 .fields = 4,
  68.         },
  69.         [VERT_ATTRIB_NORMAL] = {
  70.                 .type = GL_FLOAT,
  71.                 .fields = -1,
  72.         },
  73.         [VERT_ATTRIB_COLOR0] = {
  74.                 .type = GL_UNSIGNED_BYTE,
  75.                 .fields = 4,
  76.         },
  77.         [VERT_ATTRIB_COLOR1] = {
  78.                 .type = GL_UNSIGNED_BYTE,
  79.                 .fields = 4,
  80.         },
  81.         [VERT_ATTRIB_FOG] = {
  82.                 .type = GL_FLOAT,
  83.                 .fields = 1,
  84.         },
  85.         [VERT_ATTRIB_TEX0] = {
  86.                 .type = GL_FLOAT,
  87.                 .fields = -1,
  88.         },
  89.         [VERT_ATTRIB_TEX1] = {
  90.                 .type = GL_FLOAT,
  91.                 .fields = -1,
  92.         },
  93.         [VERT_ATTRIB_TEX2] = {
  94.                 .type = GL_FLOAT,
  95.                 .fields = -1,
  96.         },
  97.         [VERT_ATTRIB_TEX3] = {
  98.                 .type = GL_FLOAT,
  99.                 .fields = -1,
  100.         },
  101. };
  102.  
  103. static void
  104. swtnl_choose_attrs(struct gl_context *ctx)
  105. {
  106.         struct nouveau_render_state *render = to_render_state(ctx);
  107.         TNLcontext *tnl = TNL_CONTEXT(ctx);
  108.         struct tnl_clipspace *vtx = &tnl->clipspace;
  109.         static struct tnl_attr_map map[NUM_VERTEX_ATTRS];
  110.         int fields, attr, i, n = 0;
  111.  
  112.         render->mode = VBO;
  113.         render->attr_count = NUM_VERTEX_ATTRS;
  114.  
  115.         /* We always want non Ndc coords format */
  116.         tnl->vb.AttribPtr[VERT_ATTRIB_POS] = tnl->vb.ClipPtr;
  117.  
  118.         for (i = 0; i < VERT_ATTRIB_MAX; i++) {
  119.                 struct nouveau_attr_info *ha = &TAG(vertex_attrs)[i];
  120.                 struct swtnl_attr_info *sa = &swtnl_attrs[i];
  121.                 struct nouveau_array *a = &render->attrs[i];
  122.  
  123.                 if (!sa->fields)
  124.                         continue; /* Unsupported attribute. */
  125.  
  126.                 if (tnl->render_inputs_bitset & BITFIELD64_BIT(i)) {
  127.                         if (sa->fields > 0)
  128.                                 fields = sa->fields;
  129.                         else
  130.                                 fields = tnl->vb.AttribPtr[i]->size;
  131.  
  132.                         map[n++] = (struct tnl_attr_map) {
  133.                                 .attrib = i,
  134.                                 .format = swtnl_get_format(sa->type, fields),
  135.                         };
  136.  
  137.                         render->map[ha->vbo_index] = i;
  138.                         a->attr = i;
  139.                         a->fields = fields;
  140.                         a->type = sa->type;
  141.                 }
  142.         }
  143.  
  144.         _tnl_install_attrs(ctx, map, n, NULL, 0);
  145.  
  146.         FOR_EACH_BOUND_ATTR(render, i, attr)
  147.                 render->attrs[attr].stride = vtx->vertex_size;
  148.  
  149.         TAG(render_set_format)(ctx);
  150. }
  151.  
  152. static void
  153. swtnl_alloc_vertices(struct gl_context *ctx)
  154. {
  155.         struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl;
  156.  
  157.         nouveau_bo_ref(NULL, &swtnl->vbo);
  158.         swtnl->buf = nouveau_get_scratch(ctx, SWTNL_VBO_SIZE, &swtnl->vbo,
  159.                                          &swtnl->offset);
  160.         swtnl->vertex_count = 0;
  161. }
  162.  
  163. static void
  164. swtnl_bind_vertices(struct gl_context *ctx)
  165. {
  166.         struct nouveau_render_state *render = to_render_state(ctx);
  167.         struct nouveau_swtnl_state *swtnl = &render->swtnl;
  168.         struct tnl_clipspace *vtx = &TNL_CONTEXT(ctx)->clipspace;
  169.         int i;
  170.  
  171.         for (i = 0; i < vtx->attr_count; i++) {
  172.                 struct tnl_clipspace_attr *ta = &vtx->attr[i];
  173.                 struct nouveau_array *a = &render->attrs[ta->attrib];
  174.  
  175.                 nouveau_bo_ref(swtnl->vbo, &a->bo);
  176.                 a->offset = swtnl->offset + ta->vertoffset;
  177.         }
  178.  
  179.         TAG(render_bind_vertices)(ctx);
  180. }
  181.  
  182. static void
  183. swtnl_unbind_vertices(struct gl_context *ctx)
  184. {
  185.         struct nouveau_render_state *render = to_render_state(ctx);
  186.         int i, attr;
  187.  
  188.         TAG(render_release_vertices)(ctx);
  189.  
  190.         FOR_EACH_BOUND_ATTR(render, i, attr) {
  191.                 nouveau_bo_ref(NULL, &render->attrs[attr].bo);
  192.                 render->map[i] = -1;
  193.         }
  194.  
  195.         render->attr_count = 0;
  196. }
  197.  
  198. static void
  199. swtnl_flush_vertices(struct gl_context *ctx)
  200. {
  201.         struct nouveau_pushbuf *push = context_push(ctx);
  202.         struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl;
  203.         unsigned npush, start = 0, count = swtnl->vertex_count;
  204.         RENDER_LOCALS(ctx);
  205.  
  206.         swtnl_bind_vertices(ctx);
  207.  
  208.         while (count) {
  209.                 npush = get_max_vertices(ctx, NULL, PUSH_AVAIL(push));
  210.                 npush = MIN2(npush / 12 * 12, count);
  211.                 count -= npush;
  212.  
  213.                 if (!npush) {
  214.                         PUSH_KICK(push);
  215.                         continue;
  216.                 }
  217.  
  218.                 BATCH_BEGIN(nvgl_primitive(swtnl->primitive));
  219.                 EMIT_VBO(L, ctx, start, 0, npush);
  220.                 BATCH_END();
  221.  
  222.                 PUSH_KICK(push);
  223.         }
  224.  
  225.         swtnl_alloc_vertices(ctx);
  226. }
  227.  
  228. /* TnL renderer entry points */
  229.  
  230. static void
  231. swtnl_start(struct gl_context *ctx)
  232. {
  233.         swtnl_choose_attrs(ctx);
  234. }
  235.  
  236. static void
  237. swtnl_finish(struct gl_context *ctx)
  238. {
  239.         swtnl_flush_vertices(ctx);
  240.         swtnl_unbind_vertices(ctx);
  241. }
  242.  
  243. static void
  244. swtnl_primitive(struct gl_context *ctx, GLenum mode)
  245. {
  246. }
  247.  
  248. static void
  249. swtnl_reset_stipple(struct gl_context *ctx)
  250. {
  251. }
  252.  
  253. /* Primitive rendering */
  254.  
  255. #define BEGIN_PRIMITIVE(p, n)                                           \
  256.         struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl; \
  257.         int vertex_len = TNL_CONTEXT(ctx)->clipspace.vertex_size;       \
  258.                                                                         \
  259.         if (swtnl->vertex_count + (n) > SWTNL_VBO_SIZE/vertex_len       \
  260.             || (swtnl->vertex_count && swtnl->primitive != p))          \
  261.                 swtnl_flush_vertices(ctx);                              \
  262.                                                                         \
  263.         swtnl->primitive = p;
  264.  
  265. #define OUT_VERTEX(i) do {                                              \
  266.                 memcpy(swtnl->buf + swtnl->vertex_count * vertex_len,   \
  267.                        _tnl_get_vertex(ctx, (i)), vertex_len);          \
  268.                 swtnl->vertex_count++;                                  \
  269.         } while (0)
  270.  
  271. static void
  272. swtnl_points(struct gl_context *ctx, GLuint first, GLuint last)
  273. {
  274.         int i, count;
  275.  
  276.         while (first < last) {
  277.                 BEGIN_PRIMITIVE(GL_POINTS, last - first);
  278.  
  279.                 count = MIN2(SWTNL_VBO_SIZE / vertex_len, last - first);
  280.                 for (i = 0; i < count; i++)
  281.                         OUT_VERTEX(first + i);
  282.  
  283.                 first += count;
  284.         }
  285. }
  286.  
  287. static void
  288. swtnl_line(struct gl_context *ctx, GLuint v1, GLuint v2)
  289. {
  290.         BEGIN_PRIMITIVE(GL_LINES, 2);
  291.         OUT_VERTEX(v1);
  292.         OUT_VERTEX(v2);
  293. }
  294.  
  295. static void
  296. swtnl_triangle(struct gl_context *ctx, GLuint v1, GLuint v2, GLuint v3)
  297. {
  298.         BEGIN_PRIMITIVE(GL_TRIANGLES, 3);
  299.         OUT_VERTEX(v1);
  300.         OUT_VERTEX(v2);
  301.         OUT_VERTEX(v3);
  302. }
  303.  
  304. static void
  305. swtnl_quad(struct gl_context *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4)
  306. {
  307.         BEGIN_PRIMITIVE(GL_QUADS, 4);
  308.         OUT_VERTEX(v1);
  309.         OUT_VERTEX(v2);
  310.         OUT_VERTEX(v3);
  311.         OUT_VERTEX(v4);
  312. }
  313.  
  314. /* TnL initialization. */
  315. void
  316. TAG(swtnl_init)(struct gl_context *ctx)
  317. {
  318.         TNLcontext *tnl = TNL_CONTEXT(ctx);
  319.  
  320.         tnl->Driver.RunPipeline = _tnl_run_pipeline;
  321.         tnl->Driver.Render.Interp = _tnl_interp;
  322.         tnl->Driver.Render.CopyPV = _tnl_copy_pv;
  323.         tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
  324.         tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
  325.         tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
  326.  
  327.         tnl->Driver.Render.Start = swtnl_start;
  328.         tnl->Driver.Render.Finish = swtnl_finish;
  329.         tnl->Driver.Render.PrimitiveNotify = swtnl_primitive;
  330.         tnl->Driver.Render.ResetLineStipple = swtnl_reset_stipple;
  331.  
  332.         tnl->Driver.Render.Points = swtnl_points;
  333.         tnl->Driver.Render.Line = swtnl_line;
  334.         tnl->Driver.Render.Triangle = swtnl_triangle;
  335.         tnl->Driver.Render.Quad = swtnl_quad;
  336.  
  337.         _tnl_init_vertices(ctx, tnl->vb.Size,
  338.                            NUM_VERTEX_ATTRS * 4 * sizeof(GLfloat));
  339.         _tnl_need_projected_coords(ctx, GL_FALSE);
  340.         _tnl_allow_vertex_fog(ctx, GL_FALSE);
  341.         _tnl_wakeup(ctx);
  342.  
  343.         swtnl_alloc_vertices(ctx);
  344. }
  345.  
  346. void
  347. TAG(swtnl_destroy)(struct gl_context *ctx)
  348. {
  349.         nouveau_bo_ref(NULL, &to_render_state(ctx)->swtnl.vbo);
  350. }
  351.