cell: checkpoint: more multi-texture work
[mesa.git] / src / gallium / drivers / cell / ppu / cell_texture.c
1 /**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27 /*
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Michel Dänzer <michel@tungstengraphics.com>
31 */
32
33 #include "pipe/p_context.h"
34 #include "pipe/p_defines.h"
35 #include "pipe/p_inlines.h"
36 #include "pipe/p_util.h"
37 #include "pipe/p_winsys.h"
38
39 #include "cell_context.h"
40 #include "cell_state.h"
41 #include "cell_texture.h"
42
43
44 /* Simple, maximally packed layout.
45 */
46
47 static unsigned minify( unsigned d )
48 {
49 return MAX2(1, d>>1);
50 }
51
52
53 static void
54 cell_texture_layout(struct cell_texture * spt)
55 {
56 struct pipe_texture *pt = &spt->base;
57 unsigned level;
58 unsigned width = pt->width[0];
59 unsigned height = pt->height[0];
60 unsigned depth = pt->depth[0];
61
62 spt->buffer_size = 0;
63
64 for ( level = 0 ; level <= pt->last_level ; level++ ) {
65 pt->width[level] = width;
66 pt->height[level] = height;
67 pt->depth[level] = depth;
68
69 spt->level_offset[level] = spt->buffer_size;
70
71 spt->buffer_size += ((pt->compressed) ? MAX2(1, height/4) : height) *
72 ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
73 width * pt->cpp;
74
75 width = minify(width);
76 height = minify(height);
77 depth = minify(depth);
78 }
79 }
80
81
82 static struct pipe_texture *
83 cell_texture_create_screen(struct pipe_screen *screen,
84 const struct pipe_texture *templat)
85 {
86 struct pipe_winsys *ws = screen->winsys;
87 struct cell_texture *spt = CALLOC_STRUCT(cell_texture);
88 if (!spt)
89 return NULL;
90
91 spt->base = *templat;
92 spt->base.refcount = 1;
93 spt->base.screen = screen;
94
95 cell_texture_layout(spt);
96
97 spt->buffer = ws->buffer_create(ws, 32,
98 PIPE_BUFFER_USAGE_PIXEL,
99 spt->buffer_size);
100
101 if (!spt->buffer) {
102 FREE(spt);
103 return NULL;
104 }
105
106 return &spt->base;
107 }
108
109
110 static void
111 cell_texture_release_screen(struct pipe_screen *screen,
112 struct pipe_texture **pt)
113 {
114 if (!*pt)
115 return;
116
117 /*
118 DBG("%s %p refcount will be %d\n",
119 __FUNCTION__, (void *) *pt, (*pt)->refcount - 1);
120 */
121 if (--(*pt)->refcount <= 0) {
122 struct cell_texture *spt = cell_texture(*pt);
123
124 /*
125 DBG("%s deleting %p\n", __FUNCTION__, (void *) spt);
126 */
127
128 pipe_buffer_reference(screen->winsys, &spt->buffer, NULL);
129
130 FREE(spt);
131 }
132 *pt = NULL;
133 }
134
135
136 static void
137 cell_texture_update(struct pipe_context *pipe, struct pipe_texture *texture,
138 uint face, uint levelsMask)
139 {
140 /* XXX TO DO: re-tile the texture data ... */
141
142 }
143
144
145 static struct pipe_surface *
146 cell_get_tex_surface_screen(struct pipe_screen *screen,
147 struct pipe_texture *pt,
148 unsigned face, unsigned level, unsigned zslice)
149 {
150 struct pipe_winsys *ws = screen->winsys;
151 struct cell_texture *spt = cell_texture(pt);
152 struct pipe_surface *ps;
153
154 ps = ws->surface_alloc(ws);
155 if (ps) {
156 assert(ps->refcount);
157 assert(ps->winsys);
158 pipe_buffer_reference(ws, &ps->buffer, spt->buffer);
159 ps->format = pt->format;
160 ps->cpp = pt->cpp;
161 ps->width = pt->width[level];
162 ps->height = pt->height[level];
163 ps->pitch = ps->width;
164 ps->offset = spt->level_offset[level];
165
166 if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) {
167 ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) *
168 (pt->compressed ? ps->height/4 : ps->height) *
169 ps->width * ps->cpp;
170 } else {
171 assert(face == 0);
172 assert(zslice == 0);
173 }
174 }
175 return ps;
176 }
177
178
179
180 static void
181 tile_copy_data(uint w, uint h, uint tile_size, uint *dst, const uint *src)
182 {
183 const uint tile_size2 = tile_size * tile_size;
184 const uint h_t = h / tile_size, w_t = w / tile_size;
185
186 uint it, jt; /* tile counters */
187 uint i, j; /* intra-tile counters */
188
189 for (it = 0; it < h_t; it++) {
190 for (jt = 0; jt < w_t; jt++) {
191 /* fill in tile (i, j) */
192 uint *tdst = dst + (it * w_t + jt) * tile_size2;
193 for (i = 0; i < tile_size; i++) {
194 for (j = 0; j < tile_size; j++) {
195 const uint srci = it * tile_size + i;
196 const uint srcj = jt * tile_size + j;
197 *tdst++ = src[srci * h + srcj];
198 }
199 }
200 }
201 }
202 }
203
204
205
206 /**
207 * Convert linear texture image data to tiled format for SPU usage.
208 */
209 static void
210 cell_tile_texture(struct cell_context *cell,
211 struct cell_texture *texture)
212 {
213 struct pipe_screen *screen = cell->pipe.screen;
214 uint face = 0, level = 0, zslice = 0;
215 struct pipe_surface *surf;
216 const uint w = texture->base.width[0], h = texture->base.height[0];
217 const uint *src;
218
219 /* temporary restrictions: */
220 assert(w >= TILE_SIZE);
221 assert(h >= TILE_SIZE);
222 assert(w % TILE_SIZE == 0);
223 assert(h % TILE_SIZE == 0);
224
225 surf = screen->get_tex_surface(screen, &texture->base, face, level, zslice);
226 ASSERT(surf);
227
228 src = (const uint *) pipe_surface_map(surf);
229
230 if (texture->tiled_data) {
231 align_free(texture->tiled_data);
232 }
233 texture->tiled_data = align_malloc(w * h * 4, 16);
234
235 tile_copy_data(w, h, TILE_SIZE, texture->tiled_data, src);
236
237 pipe_surface_unmap(surf);
238
239 pipe_surface_reference(&surf, NULL);
240 }
241
242
243
244 void
245 cell_update_texture_mapping(struct cell_context *cell)
246 {
247 uint face = 0, level = 0, zslice = 0;
248 uint i;
249
250 for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
251 if (cell->texture[i])
252 cell_tile_texture(cell, cell->texture[i]);
253 }
254
255 #if 0
256 if (cell->tex_surf && cell->tex_map) {
257 pipe_surface_unmap(cell->tex_surf);
258 cell->tex_map = NULL;
259 }
260
261 /* XXX free old surface */
262
263 cell->tex_surf = cell_get_tex_surface(&cell->pipe,
264 &cell->texture[0]->base,
265 face, level, zslice);
266
267 cell->tex_map = pipe_surface_map(cell->tex_surf);
268 #endif
269 }
270
271
272 void
273 cell_init_texture_functions(struct cell_context *cell)
274 {
275 cell->pipe.texture_update = cell_texture_update;
276 }
277
278 void
279 cell_init_screen_texture_funcs(struct pipe_screen *screen)
280 {
281 screen->texture_create = cell_texture_create_screen;
282 screen->texture_release = cell_texture_release_screen;
283 screen->get_tex_surface = cell_get_tex_surface_screen;
284 }