freedreno_texture.c revision d4ff42bd0a80acfac080507e4e14f33f0b3bffbb
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2 3/* 4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Authors: 26 * Rob Clark <robclark@freedesktop.org> 27 */ 28 29#include "pipe/p_state.h" 30#include "util/u_string.h" 31#include "util/u_memory.h" 32#include "util/u_inlines.h" 33 34#include "freedreno_texture.h" 35#include "freedreno_context.h" 36#include "freedreno_util.h" 37 38static void 39fd_sampler_state_delete(struct pipe_context *pctx, void *hwcso) 40{ 41 FREE(hwcso); 42} 43 44static void 45fd_sampler_view_destroy(struct pipe_context *pctx, 46 struct pipe_sampler_view *view) 47{ 48 pipe_resource_reference(&view->texture, NULL); 49 FREE(view); 50} 51 52static void bind_sampler_states(struct fd_texture_stateobj *tex, 53 unsigned nr, void **hwcso) 54{ 55 unsigned i; 56 unsigned new_nr = 0; 57 58 for (i = 0; i < nr; i++) { 59 if (hwcso[i]) 60 new_nr = i + 1; 61 tex->samplers[i] = hwcso[i]; 62 tex->dirty_samplers |= (1 << i); 63 } 64 65 for (; i < tex->num_samplers; i++) { 66 tex->samplers[i] = NULL; 67 tex->dirty_samplers |= (1 << i); 68 } 69 70 tex->num_samplers = new_nr; 71} 72 73static void set_sampler_views(struct fd_texture_stateobj *tex, 74 unsigned nr, struct pipe_sampler_view **views) 75{ 76 unsigned i; 77 unsigned new_nr = 0; 78 79 for (i = 0; i < nr; i++) { 80 if (views[i]) 81 new_nr = i + 1; 82 pipe_sampler_view_reference(&tex->textures[i], views[i]); 83 tex->dirty_samplers |= (1 << i); 84 } 85 86 for (; i < tex->num_textures; i++) { 87 pipe_sampler_view_reference(&tex->textures[i], NULL); 88 tex->dirty_samplers |= (1 << i); 89 } 90 91 tex->num_textures = new_nr; 92} 93 94void 95fd_sampler_states_bind(struct pipe_context *pctx, 96 unsigned shader, unsigned start, 97 unsigned nr, void **hwcso) 98{ 99 struct fd_context *ctx = fd_context(pctx); 100 101 assert(start == 0); 102 103 if (shader == PIPE_SHADER_FRAGMENT) { 104 bind_sampler_states(&ctx->fragtex, nr, hwcso); 105 ctx->dirty |= FD_DIRTY_FRAGTEX; 106 } 107 else if (shader == PIPE_SHADER_VERTEX) { 108 bind_sampler_states(&ctx->verttex, nr, hwcso); 109 ctx->dirty |= FD_DIRTY_VERTTEX; 110 } 111} 112 113void 114fd_set_sampler_views(struct pipe_context *pctx, unsigned shader, 115 unsigned start, unsigned nr, 116 struct pipe_sampler_view **views) 117{ 118 struct fd_context *ctx = fd_context(pctx); 119 120 assert(start == 0); 121 122 switch (shader) { 123 case PIPE_SHADER_FRAGMENT: 124 /* on a2xx, since there is a flat address space for textures/samplers, 125 * a change in # of fragment textures/samplers will trigger patching 126 * and re-emitting the vertex shader: 127 * 128 * (note: later gen's ignore FD_DIRTY_TEXSTATE so fine to set it) 129 */ 130 if (nr != ctx->fragtex.num_textures) 131 ctx->dirty |= FD_DIRTY_TEXSTATE; 132 133 set_sampler_views(&ctx->fragtex, nr, views); 134 ctx->dirty |= FD_DIRTY_FRAGTEX; 135 break; 136 case PIPE_SHADER_VERTEX: 137 set_sampler_views(&ctx->verttex, nr, views); 138 ctx->dirty |= FD_DIRTY_VERTTEX; 139 break; 140 default: 141 break; 142 } 143} 144 145void 146fd_texture_init(struct pipe_context *pctx) 147{ 148 pctx->delete_sampler_state = fd_sampler_state_delete; 149 150 pctx->sampler_view_destroy = fd_sampler_view_destroy; 151} 152 153/* helper for setting up border-color buffer for a3xx/a4xx: */ 154void 155fd_setup_border_colors(struct fd_texture_stateobj *tex, void *ptr, 156 unsigned offset) 157{ 158 unsigned i, j; 159 160 for (i = 0; i < tex->num_samplers; i++) { 161 struct pipe_sampler_state *sampler = tex->samplers[i]; 162 uint16_t *bcolor = (uint16_t *)((uint8_t *)ptr + 163 (BORDERCOLOR_SIZE * offset) + 164 (BORDERCOLOR_SIZE * i)); 165 uint32_t *bcolor32 = (uint32_t *)&bcolor[16]; 166 167 if (!sampler) 168 continue; 169 170 /* 171 * XXX HACK ALERT XXX 172 * 173 * The border colors need to be swizzled in a particular 174 * format-dependent order. Even though samplers don't know about 175 * formats, we can assume that with a GL state tracker, there's a 176 * 1:1 correspondence between sampler and texture. Take advantage 177 * of that knowledge. 178 */ 179 if (i < tex->num_textures && tex->textures[i]) { 180 const struct util_format_description *desc = 181 util_format_description(tex->textures[i]->format); 182 for (j = 0; j < 4; j++) { 183 if (desc->swizzle[j] >= 4) 184 continue; 185 186 const struct util_format_channel_description *chan = 187 &desc->channel[desc->swizzle[j]]; 188 if (chan->pure_integer) { 189 bcolor32[desc->swizzle[j] + 4] = sampler->border_color.i[j]; 190 bcolor[desc->swizzle[j] + 8] = sampler->border_color.i[j]; 191 } else { 192 bcolor32[desc->swizzle[j]] = fui(sampler->border_color.f[j]); 193 bcolor[desc->swizzle[j]] = 194 util_float_to_half(sampler->border_color.f[j]); 195 } 196 } 197 } 198 } 199} 200