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. /*
  28.  * Vertex submission helper definitions shared among the software and
  29.  * hardware TnL paths.
  30.  */
  31.  
  32. #include "nouveau_gldefs.h"
  33.  
  34. #include "main/light.h"
  35. #include "vbo/vbo.h"
  36. #include "tnl/tnl.h"
  37.  
  38. #define OUT_INDICES_L(r, i, d, n)               \
  39.         BATCH_OUT_L(i + d, n);                  \
  40.         (void)r
  41. #define OUT_INDICES_I16(r, i, d, n)                             \
  42.         BATCH_OUT_I16(r->ib.extract_u(&r->ib, 0, i) + d,        \
  43.                       r->ib.extract_u(&r->ib, 0, i + 1) + d)
  44. #define OUT_INDICES_I32(r, i, d, n)                     \
  45.         BATCH_OUT_I32(r->ib.extract_u(&r->ib, 0, i) + d)
  46.  
  47. /*
  48.  * Emit <n> vertices using BATCH_OUT_<out>, MAX_OUT_<out> at a time,
  49.  * grouping them in packets of length MAX_PACKET.
  50.  *
  51.  * out:   hardware index data type.
  52.  * ctx:   GL context.
  53.  * start: element within the index buffer to begin with.
  54.  * delta: integer correction that will be added to each index found in
  55.  *        the index buffer.
  56.  */
  57. #define EMIT_VBO(out, ctx, start, delta, n) do {                        \
  58.                 struct nouveau_render_state *render = to_render_state(ctx); \
  59.                 int npush = n;                                          \
  60.                                                                         \
  61.                 while (npush) {                                         \
  62.                         int npack = MIN2(npush, MAX_PACKET * MAX_OUT_##out); \
  63.                         npush -= npack;                                 \
  64.                                                                         \
  65.                         BATCH_PACKET_##out((npack + MAX_OUT_##out - 1)  \
  66.                                            / MAX_OUT_##out);            \
  67.                         while (npack) {                                 \
  68.                                 int nout = MIN2(npack, MAX_OUT_##out);  \
  69.                                 npack -= nout;                          \
  70.                                                                         \
  71.                                 OUT_INDICES_##out(render, start, delta, \
  72.                                                   nout);                \
  73.                                 start += nout;                          \
  74.                         }                                               \
  75.                 }                                                       \
  76.         } while (0)
  77.  
  78. /*
  79.  * Emit the <n>-th element of the array <a>, using IMM_OUT.
  80.  */
  81. #define EMIT_IMM(ctx, a, n) do {                                        \
  82.                 struct nouveau_attr_info *info =                        \
  83.                         &TAG(vertex_attrs)[(a)->attr];                  \
  84.                 int m;                                                  \
  85.                                                                         \
  86.                 if (!info->emit) {                                      \
  87.                         IMM_PACKET(info->imm_method, info->imm_fields); \
  88.                                                                         \
  89.                         for (m = 0; m < (a)->fields; m++)               \
  90.                                 IMM_OUT((a)->extract_f(a, n, m));       \
  91.                                                                         \
  92.                         for (m = (a)->fields; m < info->imm_fields; m++) \
  93.                                 IMM_OUT(((float []){0, 0, 0, 1})[m]);   \
  94.                                                                         \
  95.                 } else {                                                \
  96.                         info->emit(ctx, a, (a)->buf + n * (a)->stride); \
  97.                 }                                                       \
  98.         } while (0)
  99.  
  100. static void
  101. dispatch_l(struct gl_context *ctx, unsigned int start, int delta,
  102.            unsigned int n)
  103. {
  104.         struct nouveau_pushbuf *push = context_push(ctx);
  105.         RENDER_LOCALS(ctx);
  106.  
  107.         EMIT_VBO(L, ctx, start, delta, n);
  108. }
  109.  
  110. static void
  111. dispatch_i32(struct gl_context *ctx, unsigned int start, int delta,
  112.              unsigned int n)
  113. {
  114.         struct nouveau_pushbuf *push = context_push(ctx);
  115.         RENDER_LOCALS(ctx);
  116.  
  117.         EMIT_VBO(I32, ctx, start, delta, n);
  118. }
  119.  
  120. static void
  121. dispatch_i16(struct gl_context *ctx, unsigned int start, int delta,
  122.              unsigned int n)
  123. {
  124.         struct nouveau_pushbuf *push = context_push(ctx);
  125.         RENDER_LOCALS(ctx);
  126.  
  127.         EMIT_VBO(I32, ctx, start, delta, n & 1);
  128.         EMIT_VBO(I16, ctx, start, delta, n & ~1);
  129. }
  130.  
  131. /*
  132.  * Select an appropriate dispatch function for the given index buffer.
  133.  */
  134. static dispatch_t
  135. get_array_dispatch(struct nouveau_array *a)
  136. {
  137.         if (!a->fields)
  138.                 return dispatch_l;
  139.         else if (a->type == GL_UNSIGNED_INT)
  140.                 return dispatch_i32;
  141.         else
  142.                 return dispatch_i16;
  143. }
  144.  
  145. /*
  146.  * Returns how many vertices you can draw using <n> pushbuf dwords.
  147.  */
  148. static inline unsigned
  149. get_max_vertices(struct gl_context *ctx, const struct _mesa_index_buffer *ib,
  150.                  int n)
  151. {
  152.         struct nouveau_render_state *render = to_render_state(ctx);
  153.  
  154.         if (render->mode == IMM) {
  155.                 return MAX2(0, n - 4) / (render->vertex_size / 4 +
  156.                                          render->attr_count);
  157.         } else {
  158.                 unsigned max_out;
  159.  
  160.                 if (ib) {
  161.                         switch (ib->type) {
  162.                         case GL_UNSIGNED_INT:
  163.                                 max_out = MAX_OUT_I32;
  164.                                 break;
  165.  
  166.                         case GL_UNSIGNED_SHORT:
  167.                                 max_out = MAX_OUT_I16;
  168.                                 break;
  169.  
  170.                         case GL_UNSIGNED_BYTE:
  171.                                 max_out = MAX_OUT_I16;
  172.                                 break;
  173.  
  174.                         default:
  175.                                 assert(0);
  176.                                 max_out = 0;
  177.                                 break;
  178.                         }
  179.                 } else {
  180.                         max_out = MAX_OUT_L;
  181.                 }
  182.  
  183.                 return MAX2(0, n - 7) * max_out * MAX_PACKET / (1 + MAX_PACKET);
  184.         }
  185. }
  186.  
  187. static void
  188. TAG(emit_material)(struct gl_context *ctx, struct nouveau_array *a,
  189.                    const void *v)
  190. {
  191.         int attr = a->attr - VERT_ATTRIB_GENERIC0;
  192.         int state = ((int []) {
  193.                         NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT,
  194.                         NOUVEAU_STATE_MATERIAL_BACK_AMBIENT,
  195.                         NOUVEAU_STATE_MATERIAL_FRONT_DIFFUSE,
  196.                         NOUVEAU_STATE_MATERIAL_BACK_DIFFUSE,
  197.                         NOUVEAU_STATE_MATERIAL_FRONT_SPECULAR,
  198.                         NOUVEAU_STATE_MATERIAL_BACK_SPECULAR,
  199.                         NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT,
  200.                         NOUVEAU_STATE_MATERIAL_BACK_AMBIENT,
  201.                         NOUVEAU_STATE_MATERIAL_FRONT_SHININESS,
  202.                         NOUVEAU_STATE_MATERIAL_BACK_SHININESS
  203.                 }) [attr];
  204.  
  205.         COPY_4V(ctx->Light.Material.Attrib[attr], (float *)v);
  206.         _mesa_update_material(ctx, 1 << attr);
  207.  
  208.         context_drv(ctx)->emit[state](ctx, state);
  209. }
  210.