1/*
2 * Copyright (c) 2016 Etnaviv Project
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 * Authors:
24 *    Christian Gmeiner <christian.gmeiner@gmail.com>
25 */
26
27#include "etnaviv_uniforms.h"
28
29#include "etnaviv_compiler.h"
30#include "etnaviv_context.h"
31#include "etnaviv_util.h"
32#include "pipe/p_defines.h"
33#include "util/u_math.h"
34
35static unsigned
36get_const_idx(const struct etna_context *ctx, bool frag, unsigned samp_id)
37{
38   if (frag)
39      return samp_id;
40
41   return samp_id + ctx->specs.vertex_sampler_offset;
42}
43
44static uint32_t
45get_texrect_scale(const struct etna_context *ctx, bool frag,
46                  enum etna_immediate_contents contents, uint32_t data)
47{
48   unsigned index = get_const_idx(ctx, frag, data);
49   struct pipe_sampler_view *texture = ctx->sampler_view[index];
50   uint32_t dim;
51
52   if (contents == ETNA_IMMEDIATE_TEXRECT_SCALE_X)
53      dim = texture->texture->width0;
54   else
55      dim = texture->texture->height0;
56
57   return fui(1.0f / dim);
58}
59
60void
61etna_uniforms_write(const struct etna_context *ctx,
62                    const struct etna_shader *sobj,
63                    struct pipe_constant_buffer *cb, uint32_t *uniforms,
64                    unsigned *size)
65{
66   const struct etna_shader_uniform_info *uinfo = &sobj->uniforms;
67   bool frag = false;
68
69   if (cb->user_buffer) {
70      unsigned size = MIN2(cb->buffer_size, uinfo->const_count * 4);
71
72      memcpy(uniforms, cb->user_buffer, size);
73   }
74
75   if (sobj == ctx->fs)
76      frag = true;
77
78   for (uint32_t i = 0; i < uinfo->imm_count; i++) {
79      switch (uinfo->imm_contents[i]) {
80      case ETNA_IMMEDIATE_CONSTANT:
81         uniforms[i + uinfo->const_count] = uinfo->imm_data[i];
82         break;
83
84      case ETNA_IMMEDIATE_TEXRECT_SCALE_X:
85      case ETNA_IMMEDIATE_TEXRECT_SCALE_Y:
86         uniforms[i + uinfo->const_count] =
87               get_texrect_scale(ctx, frag, uinfo->imm_contents[i], uinfo->imm_data[i]);
88         break;
89
90      case ETNA_IMMEDIATE_UNUSED:
91         /* nothing to do */
92         break;
93      }
94   }
95
96   *size = uinfo->const_count + uinfo->imm_count;
97}
98
99void
100etna_set_shader_uniforms_dirty_flags(struct etna_shader *sobj)
101{
102   uint32_t dirty = 0;
103
104   for (uint32_t i = 0; i < sobj->uniforms.imm_count; i++) {
105      switch (sobj->uniforms.imm_contents[i]) {
106      case ETNA_IMMEDIATE_UNUSED:
107      case ETNA_IMMEDIATE_CONSTANT:
108         break;
109
110      case ETNA_IMMEDIATE_TEXRECT_SCALE_X:
111      case ETNA_IMMEDIATE_TEXRECT_SCALE_Y:
112         dirty |= ETNA_DIRTY_SAMPLER_VIEWS;
113         break;
114      }
115   }
116
117   sobj->uniforms_dirty_bits = dirty;
118}
119